package com.example.hctorisrael.deadolympics;

import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

import org.andengine.audio.music.Music;
import org.andengine.audio.music.MusicFactory;
import org.andengine.audio.sound.Sound;
import org.andengine.audio.sound.SoundFactory;
import org.andengine.engine.camera.Camera;
import org.andengine.entity.scene.background.SpriteBackground;
import org.andengine.entity.scene.menu.MenuScene;
import org.andengine.entity.scene.menu.item.IMenuItem;
import org.andengine.entity.scene.menu.item.SpriteMenuItem;
import org.andengine.entity.scene.menu.item.decorator.ScaleMenuItemDecorator;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.ButtonSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.opengl.util.GLState;

import java.io.IOException;
import java.util.ArrayList;

/**
 * Created by HéctorIsrael on 19/04/2015.
 */
public class EscenaJuegoDos extends EscenaBase implements SensorEventListener{

    //SONIDOS*****
    private Music musicaFondo;
    private Sound efectoDisparo;
    private Sound efectoCabeza;
    //Pausa
    private MenuScene escenaPausa;
    private Sprite fondoPausa;
    private final int OPCION_CONTINUAR = 0;
    private final int OPCION_MENU = 1;
    private Sprite spriteBtnPausa;
    private boolean estaEnPausa = false;
    //SPRITE TIMER
    private AnimatedSprite timer;
    //CONTADOR TIEMPO
    private int tiempo = 600;
    //MENSAJES GANASTE / PERDISTE
    private Sprite mensajePerdiste;
    private Sprite mensajeGanaste;
    //FONDO
    private Sprite spriteFondoJuegoDos;
    //PERSONAJE
    private Sprite spriteShooter;
    //PERSONAJE Con disparo
    private Sprite spriteShooterDisparo;
    // Sensor de GRAVEDAD
    private SensorManager admSensores; // Administra TODOS los sensores del dispositivo
    private Sensor sensorGravedad;      // El sensor específico de gravedad
    //BALA
    private Bala bala;
    private Bala temp;
    private boolean disparo = false;
    //cabezas
    private cabezaHombre cabezaH;
    private cabezaHombre tempCH;
    private boolean salio = false;
    private boolean acabo=false;
    private int caidas=0;
    //Sprite shooter muriendo
    private AnimatedSprite SpriteShooterMuriendo;
    //Marcador
    public Marcador marcador;
    //Tiempo para agregar cabezas
    private float tiempoTranscurrido;
    ArrayList<Bala> lista = new ArrayList<>();
    ArrayList<cabezaHombre> listaCH = new ArrayList<>();
    public int puntaje = 0;
    private int cont =0;


    private float espera;

    @Override
    public void crearEscena() {

        spriteFondoJuegoDos = new Sprite(0,0, admRecursos.regionFondoJuegoDos,admRecursos.vbom) {
            @Override
            protected void preDraw(GLState pGLState, Camera pCamera) {
                super.preDraw(pGLState, pCamera);
                pGLState.enableDither();
            }
        };
        // Configuración de la imagen
        spriteFondoJuegoDos.setPosition(ControlJuego.ANCHO_CAMARA/2,ControlJuego.ALTO_CAMARA/2);
        // Crea el fondo de la pantalla
        SpriteBackground fondo = new SpriteBackground(0,0,0,spriteFondoJuegoDos);
        setBackground(fondo);
        setBackgroundEnabled(true);
        agregarShooter();
        //inicializarSensor();
        agregarShooterConDisparo();
        agregarMarcador();
        agregarBtnPausa();
        crearEscenaPausa();
        agregarTimerAnimado();
        crearSonidos();
    };

    protected void onManagedUpdate(float pSecondsElapsed){
        if(estaEnPausa){
            musicaFondo.pause();
            setIgnoreUpdate(true);  // Ya no ejecuta este método
            pausar(); // Mostrar la escena de pausa
            return;
        }
        tiempo--;

        if(!acabo) {
            //aumentando el puntaje

            //1.5 segundos para que el shooter no se mueva
            espera+= pSecondsElapsed;
            if( espera>=1.50){
                inicializarSensor();

            }

            //CAMBIA LA ORIENTACION DEL SPRITE DISPARANDO
            if (spriteShooterDisparo.getX() > ControlJuego.ANCHO_CAMARA / 2) {
                spriteShooterDisparo.setFlippedHorizontal(true);
            }
            if (spriteShooter.getX() > ControlJuego.ANCHO_CAMARA / 2) {
                spriteShooter.setFlippedHorizontal(true);
            }
            if (spriteShooter.getX() < ControlJuego.ANCHO_CAMARA / 2) {
                spriteShooter.setFlippedHorizontal(false);
            }
            if (spriteShooterDisparo.getX() < ControlJuego.ANCHO_CAMARA / 2) {
                spriteShooterDisparo.setFlippedHorizontal(false);
            }


            for (int i = lista.size() - 1; i >= 0; i--) {
                temp = lista.get(i);
                //Cambia el sentido de la bala
                if (spriteShooterDisparo.getX() > ControlJuego.ANCHO_CAMARA / 2 && spriteShooter.getX() > ControlJuego.ANCHO_CAMARA / 2) {
                    temp.moverBala(-11, 7);
                    bala.getSpriteBala().setFlippedHorizontal(true);

                }
                if (spriteShooterDisparo.getX() < ControlJuego.ANCHO_CAMARA / 2 && spriteShooter.getX() < ControlJuego.ANCHO_CAMARA / 2) {
                    temp.moverBala(11, 7);

                }
                //Cuando la bala sale de la pantalla se elimina
                if (temp.getSpriteBala().getX() > 800 || temp.getSpriteBala().getY() > 520) {
                    temp.getSpriteBala().detachSelf();
                    lista.remove(temp);
                }

                if (disparo == true && salio == true && temp.getSpriteBala().collidesWith(tempCH.getSpriteCabezaHombre())) {
                    tempCH.getSpriteCabezaHombre().detachSelf();
                    temp.getSpriteBala().detachSelf();
                    lista.remove(temp);
                    puntaje++;
                    listaCH.remove(tempCH);

                }
            }


            tiempoTranscurrido += pSecondsElapsed;
            //Cabezas
            if (tiempoTranscurrido > 1 && acabo == false) {
                // Crea una Cabeza
                float xa = (float) (Math.random() * ControlJuego.ANCHO_CAMARA);
                //float ya = (float) (Math.random()*ControlJuego.ALTO_CAMARA);
                cabezaH = new cabezaHombre(xa, 480, admRecursos.regionCabezaHombre, admRecursos.vbom);
                attachChild(cabezaH.getSpriteCabezaHombre()); // AGREGA a la ESCENA
                listaCH.add(cabezaH);  // Agrega en la lista
                tiempoTranscurrido = 0;  // Reinicia el contador de tiempo
                salio = true;
            }

            for (int i = listaCH.size() - 1; i >= 0; i--) {
                tempCH = listaCH.get(i);
                tempCH.moverCabeza(0, -4);
                tempCH.girarCabeza(5);
                if (tempCH.getSpriteCabezaHombre().getY() < 0) { //Si la cabeza sale de la pantalla
                    tempCH.getSpriteCabezaHombre().detachSelf();
                    listaCH.remove(tempCH);
                    caidas++;
                }

            }
            if (tiempo == 0 && caidas < 3) {
                agregarMensajeGanaste();
                setIgnoreUpdate(true);
                marcador.aumentarMarcador(puntaje * 25);
                modificarVidas();
                siguienteEscena();
                acabo = true;

                return;

            }

            if (caidas == 3) {
                efectoCabeza.play();
                marcador.disminuirVidas(1);
                modificarVidas();
                agregarShooterMuriendo();
                spriteShooter.detachSelf();
                spriteShooterDisparo.detachSelf();
                timer.detachSelf();
                acabo = true;


                tempCH.getSpriteCabezaHombre().detachSelf();
                cont = 1;
                return;
            }

        }

        if(cont ==1){
            if(!SpriteShooterMuriendo.isAnimationRunning()){
                SpriteShooterMuriendo.detachSelf();
                SpriteShooterMuriendo.dispose();
                siguienteEscena();
            }
        }

        super.onManagedUpdate(pSecondsElapsed);

    }



    public void agregarMarcador() {
        marcador = new Marcador(admRecursos.engine, admRecursos.actividadJuego);
        admRecursos.camara.setHUD(marcador);
        marcador.quitarMarcadorMasAlto();
        marcador.quitarMarcadorMasAltoDos();
        marcador.quitarMarcador();
        marcador.quitarVidas();

        // Para marcador más alto. PRIMERO lee el marcador anterior
        SharedPreferences preferencias = admRecursos.actividadJuego.getSharedPreferences(
                "Estado", Context.MODE_PRIVATE);
        int vidas = preferencias.getInt("vidas",marcador.getVidas());
        marcador.setVidas(vidas);

        //para leer el putnaje actual
        int puntaje = preferencias.getInt("puntaje",marcador.getMarcador());
        marcador.setMarcador(puntaje);

        //puntaj mas alto
        int ultimoMarcador = preferencias.getInt("First",marcador.getMarcadorMasAlto());
        marcador.setMarcadorMasAlto(ultimoMarcador);

        //Segundo mas alto
        int penultimoMarcador = preferencias.getInt("Second",marcador.getMarcadorMasAlto());
        marcador.setMarcadorMasAltoDos(penultimoMarcador);



    }

    private void modificarVidas() {

        // guardarlo en las preferencias
        SharedPreferences preferencias = admRecursos.actividadJuego.getSharedPreferences(
                "Estado", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = preferencias.edit();
        editor.putInt("vidas",marcador.getVidas());
        editor.putInt("puntaje", marcador.getMarcador());
        editor.commit();

        int masAlto = marcador.getMarcadorMasAlto();
        int segundoMasAlto = marcador.getMarcadorMasAltoDos();
        int puntos = marcador.getMarcador();
        if (puntos>=masAlto) {
            editor.putInt("First",masAlto);
            editor.commit();
        }
        if(puntos>=segundoMasAlto && puntos<masAlto){
            editor.putInt("Second",segundoMasAlto);
            editor.commit();
        }

    }



    //Sprite del shooter muriendo
    private void agregarShooterMuriendo() {
        TiledTextureRegion regionMunecoCorriendo = admRecursos.regionShooterMuriendo;
        SpriteShooterMuriendo = new AnimatedSprite(400, 180,
                regionMunecoCorriendo, admRecursos.vbom);


        long tiempos[] = new long[16];
        for (int i = 0; i < tiempos.length; i++) {
            tiempos[i] = 60;
        }

        //Se agrega a la escena
        SpriteShooterMuriendo.animate(tiempos, 0,tiempos.length-1,false);
        //SpriteShooterMuriendo.setAnchorCenter(0.5f,0.0f);
        attachChild(SpriteShooterMuriendo);
    }


    //Método del Timer
    private void agregarTimerAnimado() {
        TiledTextureRegion regionTimer = admRecursos.regionTimerDos;
        timer = new AnimatedSprite(ControlJuego.ANCHO_CAMARA -45, regionTimer.getHeight()+345,
                regionTimer, admRecursos.vbom);
        // Arreglo de tiempos para los frames
        long tiempos[] = new long[11];
        for (int i = 0; i < tiempos.length; i++) {
            tiempos[i] = 1000;
        }
        //Se agrega a la escena
        timer.animate(tiempos,0,tiempos.length-1,false);
        attachChild(timer);
    }

    private void agregarMensajePerdiste() {
        // Creamos el sprite de manera óptima
        mensajePerdiste = new Sprite(ControlJuego.ANCHO_CAMARA / 2, ControlJuego.ALTO_CAMARA / 2,
                admRecursos.regionPerdiste, admRecursos.vbom) {
            @Override
            protected void preDraw(GLState pGLState, Camera pCamera) {
                super.preDraw(pGLState, pCamera);
                pGLState.enableDither();
            }


        };

        attachChild(mensajePerdiste);

    }

    private void agregarShooter(){
        spriteShooter = new Sprite(ControlJuego.ANCHO_CAMARA / 2, 0,
                admRecursos.regionShooter, admRecursos.vbom) {
            @Override
            protected void preDraw(GLState pGLState, Camera pCamera) {
                super.preDraw(pGLState, pCamera);
                pGLState.enableDither();
            }


        };

        spriteShooter.setAnchorCenter(0.5f,0.0f);
        attachChild(spriteShooter);

    }

    private void agregarShooterConDisparo(){
        spriteShooterDisparo = new Sprite(ControlJuego.ANCHO_CAMARA / 2, 0,
                admRecursos.regionShooterDisparo, admRecursos.vbom) {
            @Override
            protected void preDraw(GLState pGLState, Camera pCamera) {
                super.preDraw(pGLState, pCamera);
                pGLState.enableDither();
            }
        };

        spriteShooterDisparo.setVisible(false);
        spriteShooterDisparo.setAnchorCenter(0.5f,0.0f);
        attachChild(spriteShooterDisparo);

    }


    private void inicializarSensor() {
        admSensores = (SensorManager)admRecursos.actividadJuego.getSystemService(Context.SENSOR_SERVICE);
        sensorGravedad = admSensores.getDefaultSensor(Sensor.TYPE_GRAVITY);
        if (sensorGravedad!=null) {
            admSensores.registerListener(this,sensorGravedad,SensorManager.SENSOR_DELAY_GAME);
        } else {
            Log.i("SENSOR", "No hay sensor en tu dispositivo");
        }
    }

    // *** El sensor ha cambiado

    public void onSensorChanged(SensorEvent event) {
        // Leer los valores del sensor y en base a ellos, mover el matamoscas

        // event.values es un arreglo de tipo float con 3 datos
        // cada elemento es la gravedad medida en x,y,z
        float nuevaX = spriteShooter.getX() + event.values[1] * 5;
        if (nuevaX < ControlJuego.ANCHO_CAMARA && nuevaX >= 0) {
            spriteShooter.setX(nuevaX);
        }
        float nuevaXD = spriteShooterDisparo.getX() + event.values[1] * 5;
        if (nuevaXD < ControlJuego.ANCHO_CAMARA && nuevaX >= 0) {
            spriteShooterDisparo.setX(nuevaXD);
        }

    }


    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }


    private void agregarMensajeGanaste() {
        // Creamos el sprite de manera óptima
        mensajeGanaste = new Sprite(ControlJuego.ANCHO_CAMARA / 2, ControlJuego.ALTO_CAMARA / 2,
                admRecursos.regionGanaste, admRecursos.vbom) {
            @Override
            protected void preDraw(GLState pGLState, Camera pCamera) {
                super.preDraw(pGLState, pCamera);
                pGLState.enableDither();
            }


        };

        attachChild(mensajeGanaste);

    }

    public boolean onSceneTouchEvent(TouchEvent pSceneTouchEvent) {

        if(estaEnPausa==true){
            return super.onSceneTouchEvent(pSceneTouchEvent);
        }

        if(pSceneTouchEvent.isActionDown() && spriteShooter.getX()< ControlJuego.ANCHO_CAMARA/2 && spriteShooterDisparo.getX() < ControlJuego.ANCHO_CAMARA/2){
            efectoDisparo.play();
            spriteShooterDisparo.setVisible(true);
            disparo = true;
            bala = new Bala(spriteShooterDisparo.getX()+59,spriteShooterDisparo.getY()+145, admRecursos.regionBala, admRecursos.vbom);
            attachChild(bala.getSpriteBala());
            lista.add(bala);

        }

        if(pSceneTouchEvent.isActionDown() && spriteShooter.getX()> ControlJuego.ANCHO_CAMARA/2 && spriteShooterDisparo.getX() > ControlJuego.ANCHO_CAMARA/2){
            efectoDisparo.play();
            spriteShooterDisparo.setVisible(true);
            disparo = true;
            bala = new Bala(spriteShooterDisparo.getX()-59,spriteShooterDisparo.getY()+145, admRecursos.regionBala, admRecursos.vbom);
            attachChild(bala.getSpriteBala());
            lista.add(bala);

        }
        if(pSceneTouchEvent.isActionUp()){
            spriteShooterDisparo.setVisible(false);

        }
        return super.onSceneTouchEvent(pSceneTouchEvent);


    }

    private void crearSonidos(){
        try {
            musicaFondo = MusicFactory.createMusicFromAsset(admRecursos.engine.getMusicManager(),
                    admRecursos.actividadJuego, "Niveles.mp3");
        }
        catch (IOException e) {
            Log.i("cargarSonidos", "No se puede cargar demo.ogg");
        }
        musicaFondo.setLooping(true);
        musicaFondo.play();
        try {
            efectoDisparo = SoundFactory.createSoundFromAsset(admRecursos.engine.getSoundManager(),
                    admRecursos.actividadJuego, "gunShot.wav");
            efectoCabeza = SoundFactory.createSoundFromAsset(admRecursos.engine.getSoundManager(),
                    admRecursos.actividadJuego, "cabeza.wav");
        } catch (final IOException e) {
            Log.i("cargarSonidos","No se puede cargar efecto de sonido");
        }
        efectoDisparo.setVolume(0.5f);
        efectoCabeza.setVolume(0.5f);
    }

    //Escena que ejecuta la pausa
    private void crearEscenaPausa(){
        escenaPausa = new MenuScene(admRecursos.camara);
        escenaPausa.setPosition(ControlJuego.ANCHO_CAMARA/2,ControlJuego.ALTO_CAMARA/2);

        //Fondo
        fondoPausa = new Sprite(ControlJuego.ANCHO_CAMARA/2,ControlJuego.ALTO_CAMARA/2,admRecursos.regionFondoPausaDos,admRecursos.vbom);
        SpriteBackground fondo = new SpriteBackground(0,0,0,fondoPausa);
        escenaPausa.setBackground(fondo);
        escenaPausa.setBackgroundEnabled(true);

        //Botones
        final IMenuItem opcionContinuar = new ScaleMenuItemDecorator(new SpriteMenuItem(OPCION_CONTINUAR,
                admRecursos.regionBotonContinuarDos,admRecursos.vbom), 1.5f, 1);
        final IMenuItem opcionMenu = new ScaleMenuItemDecorator(new SpriteMenuItem(OPCION_MENU,
                admRecursos.regionBotonMenuDos,admRecursos.vbom),1.5f,1);
        escenaPausa.addMenuItem(opcionContinuar);
        escenaPausa.addMenuItem(opcionMenu);
        escenaPausa.buildAnimations();
        opcionContinuar.setPosition(0,20);
        opcionMenu.setPosition(0,-70);

        escenaPausa.setOnMenuItemClickListener(new MenuScene.IOnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClicked(MenuScene pMenuScene, IMenuItem pMenuItem, float pMenuItemLocalX, float pMenuItemLocalY) {
                switch (pMenuItem.getID()) {
                    case OPCION_CONTINUAR:
                        escenaPausa.back(false);
                        estaEnPausa = false;
                        EscenaJuegoDos.this.setIgnoreUpdate(false);
                        Log.i("Pausa", "Pausa");
                        break;
                    case OPCION_MENU:
                        regresarAMenu();
                        break;
                    default:
                        return false;
                }
                return true;
            }
        });
    }

    private void pausar(){
        setChildScene(escenaPausa, false, true, true);
    }

    private void agregarBtnPausa() {
        // Habilita los eventos de touch en ciertas áreas
        setTouchAreaBindingOnActionDownEnabled(true);
        spriteBtnPausa = new ButtonSprite(150,450,admRecursos.regionBtnPausaDos, admRecursos.vbom) {
            @Override
            public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                if (pSceneTouchEvent.isActionUp()) {
                    estaEnPausa = true;
                }
                return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
            }
        };
        // Registra el área del botón
        registerTouchArea(spriteBtnPausa);
        attachChild(spriteBtnPausa);
    }

    // Regresar al menú principal
    private void regresarAMenu() {
        musicaFondo.stop();
        efectoDisparo.stop();
        efectoCabeza.stop();
        admEscenas.crearEscenaMenu();
        admEscenas.setEscena(TipoEscena.ESCENA_MENU);
        admEscenas.liberarEscenaJuegoDos();
        admRecursos.camara.setHUD(null);

    }

    private void siguienteEscena(){
        musicaFondo.stop();
        efectoDisparo.stop();
        efectoCabeza.stop();
        admEscenas.crearEscenaEstado();
        admEscenas.setEscena(TipoEscena.ESCENA_ESTADO);
        admEscenas.liberarEscenaJuegoDos();
        admRecursos.camara.setHUD(null);

    }

    // El usuario oprime el botón de BACK; regresar al menú principal
    @Override
    public void onBackKeyPressed() {
        if(estaEnPausa){
            escenaPausa.back();
            estaEnPausa = false;
            EscenaJuegoDos.this.setIgnoreUpdate(false);
        }
        //regresarAMenu();
    }

    @Override
    public TipoEscena getTipoEscena() {
        return TipoEscena.ESCENA_JUEGO;
    }

    @Override
    public void liberarEscena() {
        // Liberar cada recurso usado en esta escena
        admRecursos.camara.setHUD(null);
        musicaFondo.release();
        efectoDisparo.release();
        this.detachSelf();      // La escena misma se deconecta del engine
        this.dispose();         // Libera la memoria
    }


    public Music getMusicaFondo() {
        return musicaFondo;
    }
}
